package gestionSimpleATester;

import java.util.Collection;
import java.util.Vector;
import java.util.Iterator;

public class Account {
	
	/**
	 * Initializes the owner, amount, overdraft and the account number with parameters
	 * The method also initializes the history with a new empty Vector
	 */
	
	public Account(Person p, float a, float o, int n){
		this.owner = p;
		this.balance = a;
		this.overdraft = o;
		/******** add the initialization of the attribute 'number' *********/ 
		this.number = n;
		this.history = new Vector();
		
		/************** ERROR #Linking the client to his account ******************/
	
		
	}


	/**
	 *  Adds the amount to the current balance
	 *  Adds this operation in the history
	 * @throws Exception 
	 */
	public void deposit(float amount) throws Exception {
		/**
		 * BUG FIXED : need to check that the deposit is positive
		 */
		if(amount<0){
			throw new Exception("Could not proceed deposit, the deposit needs to be positive");
		}
		balance = balance + amount;
		/**** have to add the operation to the history****/
		DepositOperation dO = new DepositOperation(amount);
		dO.setAmount(amount);
		this.addHistory(dO);
	}

	/**
	 * (BUG FIXED to respect the semantic of withdrawals)
	 * If the new amount is greater or equal to 0, withdraws the amount
	 * If the new amount is lower than 0 and the sum between of the new amount and the overdraft is greater or equal to 0, 
	 * withdraws the amount and throws an exception to warn that the balance is negative
	 * else the amount is not withdrawn and exception is thrown to indicate that there is not enough credit.	
	 */
	public void withdraw(float amount) throws Exception {
		/**
		 * BUG FIXED : need to check that the withdrawal is positive
		 */
		if(amount<0){
			throw new Exception("Could not proceed withdrawal, the withdrawal needs to be positive");
		}
		
		float newBalance = balance - amount;
		if (newBalance >= 0){
			balance = newBalance;
			WithdrawOperation wo = new WithdrawOperation(amount);
			addHistory(wo);
		}
		else{
			/**
			 * BUG Fixed : the sum of the new balance and the overdraft must be greater or equal to 0
			 */
			if (newBalance+overdraft>=0){ 
				balance = newBalance;
				WithdrawOperation wo = new WithdrawOperation(amount);
				addHistory(wo);
				throw new Exception("Warning: the balance is negative: "+balance);
			
			}
			else{
				throw new Exception("Could not proceed withdrawal. Not enough credit.");
			}
		}
	}




	/**
	 *  
	 * This attribute memorizes the current balance of the account
	 * 
	 */
	private float balance;




	/**
	 *  
	 * this is the maximum overdraft authorized for this account
	 * 
	 */
	private float overdraft;



	/**
	 *  
	 * @uml.property name="history"
	 * @uml.associationEnd inverse="compte:gestionSimpleATester.Operation" multiplicity="(0 -1)"
	 * 
	 */
	private Collection history;


/**
	 * 
	 * @uml.property name="history"
	 */
	public java.util.Collection getHistory() {
		return history;
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public void setHistory(java.util.Collection value) {
		history = value;
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public Iterator historyIterator() {
		return history.iterator();
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public boolean addHistory(gestionSimpleATester.Operation element) {
		return history.add(element);
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public boolean removeHistory(gestionSimpleATester.Operation element) {
		return history.remove(element);
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public boolean isHistoryEmpty() {
		return history.isEmpty();
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public void clearHistory() {
		history.clear();
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public boolean containsHistory(gestionSimpleATester.Operation element) {
		return history.contains(element);
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public boolean containsAllHistory(Collection elements) {
		return history.containsAll(elements);
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public int historySize() {
		return history.size();
	}

	/**
	 * 
	 * @uml.property name="history"
	 */
	public gestionSimpleATester.Operation[] historyToArray() {
		return (gestionSimpleATester.Operation[]) history
			.toArray(new gestionSimpleATester.Operation[history.size()]);
	}

	/**
	 *  
	 * @uml.property name="overdraft"
	 * 
	 */
	public float getOverdraft() {
		return overdraft;
	}

	/**
	 *  
	 * @uml.property name="overdraft"
	 * 
	 */
	public void setOverdraft(float overdraft) {
		this.overdraft = overdraft;
	}

	/**
	 *  
	 * @uml.property name="balance"
	 * 
	 */
	public float getBalance() {
		return balance;
	}

	/**
	 *  
	 * @uml.property name="balance"
	 * 
	 */
	public void setBalance(float balance) {
		this.balance = balance;
	}

	/**
	 *  
	 * this is the number of the account
	 * 
	 */
	private int number;

	/**
	 *  
	 * @uml.property name="number"
	 * 
	 */
	public int getNumber() {
		return number;
	}

	/**
	 *  
	 * @uml.property name="number"
	 * 
	 */
	public void setNumber(int number) {
		this.number = number;
	}

	/**
	 *  
	 * @uml.property name="owner"
	 * @uml.associationEnd inverse="accounts:gestionSimpleATester.Person" multiplicity="(0 1)"
	 * 
	 */
	private Person owner;

	/**
	 *  
	 * @uml.property name="owner"
	 * 
	 */
	public Person getOwner() {
		return owner;
	}

	/**
	 *  
	 * @uml.property name="owner"
	 * 
	 */
	public void setOwner(Person owner) {
		this.owner = owner;
	}

}
